package com.mxpio.erp.equipment.service.impl;

import com.alibaba.excel.util.DateUtils;
import com.mxpio.erp.common.equipment.entity.*;
import com.mxpio.erp.common.equipment.service.*;
import com.mxpio.erp.common.equipment.vo.EquipmentCheckTaskPage;
import com.mxpioframework.common.exception.MBootException;
import com.mxpioframework.jpa.JpaUtil;
import com.mxpioframework.jpa.lin.Linq;
import com.mxpioframework.jpa.query.Criteria;
import com.mxpioframework.security.entity.User;
import com.mxpioframework.security.entity.UserDept;
import com.mxpioframework.security.service.DeptService;
import com.mxpioframework.security.util.SecurityUtils;
import com.mxpioframework.system.service.impl.BaseServiceImpl;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 点检任务
 * @Author: jeecg-boot
 * @Date: 2021-09-23
 * @Version: V1.0
 */
@Service
public class EquipmentCheckTaskServiceImpl extends BaseServiceImpl<EquipmentCheckTask> implements EquipmentCheckTaskService {

    @Autowired
    private EquipmentCommParametersDetailService equipmentCommParametersDetailService;
    @Autowired
    private EquipmentAreaService equipmentAreaService;
    @Autowired
    private EquipmentCheckTaskDetailParamService equipmentCheckTaskDetailParamService;
    @Autowired
    private EquipmentPersonGroupDetailService equipmentPersonGroupDetailService;
    @Autowired
    private EquipmentPersonGroupService equipmentPersonGroupService;
    @Autowired
    private DeptService sysDepartService;
    @Autowired
    private EquipmentCheckTaskDetailService equipmentCheckTaskDetailService;
    @Autowired
    private EquipmentCheckTaskTransferService equipmentCheckTaskTransferService;

    public static final Integer STATUS_START = 10;
    public static final Integer STATUS_RELEASE = 20;
    public static final Integer STATUS_WAIT_EXECUT = 30;
    public static final Integer STATUS_EXECUT = 40;
    public static final Integer STATUS_END = 50;
    public static final String AREA_TARGET = "area";
    public static final String EQP_TARGET = "equipment";
    public static final String DEPART_RELEASE_TARGET = "department";
    public static final String PERSON_GROUP_RELEASE_TARGET = "person_group";
    public static final String PERSONAL_RELEASE_TARGET = "personal";
    public static final String ASSIGN_MODE = "assign";
    public static final String GRAB_MODE = "grab";


    @Override
    public Page<EquipmentCheckTask> getEquipmentCheckTaskIPage(EquipmentCheckTask equipmentCheckTask, @RequestParam(name = "flag", required = true) String flag, @RequestParam(name = "planStart", required = false) String planStart, @RequestParam(name = "planEnd", required = false) String planEnd, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, Criteria criteria) {
        User loginUser = SecurityUtils.getLoginUser();
        Integer orderStatus = equipmentCheckTask.getOrderStatus();
        equipmentCheckTask.setOrderStatus(null);
        Linq linq = JpaUtil.linq(EquipmentCheckTask.class).select("*").where(criteria);

        if ("task".equals(flag)) {
            // todo 需要测试校验sql的拼接是否正确，且是否重新赋值linq
            //查询相关工单
            linq = linq.or().equal("director", loginUser.getUsername())
                        .equal("executor", loginUser.getUsername())
                        .equal("dispatchUser", loginUser.getUsername())
                        .equal("createBy", loginUser.getUsername())
                       .end();

            if (orderStatus!=null){
                linq = linq.equal("orderStatus", orderStatus);
            }
        }else if ("release".equals(flag)) {
            linq.equal("orderStatus", 10);
            //查询相关工单
            linq.or().equal("director", loginUser.getUsername())
                   .equal("executor", loginUser.getUsername())
                    .equal("dispatchUser", loginUser.getUsername())
                    .equal("dispatchUser", loginUser.getUsername())
                    .equal("createBy", loginUser.getUsername())
                    .end();
        } else if ("send".equals(flag)) {
            linq.equal("orderStatus", 20);
            //派工模式为派工
            linq.equal("dispatchMode", "assign");
            //部门主管
            linq.equal("director", loginUser.getUsername());
        } else if ("grab".equals(flag)) {
            linq.equal("orderStatus", 20);
            //派工模式为抢单
            linq.equal("dispatchMode", "grab");
            //获取当前用户的所属部门
            Set<String> deps = sysDepartService.getDeptKeysByUser(loginUser.getUsername(), "id");
            //获取当前用户所属的群组
            List<String> groups = equipmentPersonGroupDetailService.selectByUsername(loginUser.getUsername());
            List<String> departs = new ArrayList<>(deps);
            groups.addAll(departs);
            linq.in("releaseTargetId", groups);
        } else if ("execute".equals(flag)) {
            linq.in("orderStatus", 30, 40);
            linq.equal("executor", loginUser.getUsername());
        }else if ("toExecute".equals(flag)) {
            linq.equal("orderStatus", 30);
            linq.equal("executor", loginUser.getUsername());
        }else if ("executing".equals(flag)) {
            linq.equal("orderStatus", 40);
            linq.equal("executor", loginUser.getUsername());
        } else if ("record".equals(flag)) {
            linq.equal("orderStatus", 50);
            //查询相关工单
            linq.or().equal("director", loginUser.getUsername())
                    .equal("executor", loginUser.getUsername())
                    .equal("dispatchUser", loginUser.getUsername())
                    .equal("dispatchUser", loginUser.getUsername())
                    .equal("createBy", loginUser.getUsername())
                    .end();
        } else if ("executeOverdue".equals(flag)) {//逾期未执行
            //查询状态为20,30,35
            linq.in("orderStatus", 30, 40);
            //查询当前用户为执行人
            linq.equal("executor", loginUser.getUsername());
            //当前时间大于预计完成时间的未完工工单
            linq.lt("actualEndTime", DateUtils.format(new Date(),DateUtils.DATE_FORMAT_17));
        } else if ("overdueFinish".equals(flag)) {//逾期完成
            //查询状态为20,30,35
            linq.equal("orderStatus", 50);
            //查询当前用户为相关人
            linq.or().equal("director", loginUser.getUsername())
                    .equal("executor", loginUser.getUsername())
                    .equal("dispatchUser", loginUser.getUsername())
                    .equal("dispatchUser", loginUser.getUsername())
                    .equal("createBy", loginUser.getUsername())
                    .end();
            //当前时间大于预计完成时间的未完工工单
            linq.ge("actualEndTime", "planEndTime");
        }


        if (planStart != null) {
            linq.ge("plan_start_time", planStart + " 00:00:00");
        }
        if (planEnd != null) {
            linq.le("plan_end_time", planEnd + " 23:59:59");
        }
        Pageable page = PageRequest.of(pageNo-1, pageSize);
        return linq.paging(page);
    }

    @Override
    @Transactional
    public void saveMain(EquipmentCheckTask equipmentCheckTask, List<EquipmentCheckTaskDetail> equipmentCheckTaskDetailList, List<EquipmentCheckTaskTransfer> equipmentCheckTaskTransferList) throws MBootException {
        equipmentCheckTask.setOrderStatus(STATUS_START);
        if (AREA_TARGET.equals(equipmentCheckTask.getTargetType())) {
            // 查询区域信息
            EquipmentArea area = equipmentAreaService.getById(EquipmentArea.class,equipmentCheckTask.getTargetId());
            if (area == null) {
                return;
            }
            equipmentCheckTask.setTargetCode(area.getAreaCode());
            if (area.getPid() != null && !"0".equals(area.getPid())) {
                String parentAllName = equipmentAreaService.getParentAllNameByPid(area.getPid());
                equipmentCheckTask.setTargetName(parentAllName +"/"+ area.getAreaName());
            } else {
                equipmentCheckTask.setTargetName(area.getAreaName());
            }
        }
        // 获取部门或群组的负责人
        if (DEPART_RELEASE_TARGET.equals(equipmentCheckTask.getReleaseTargetType())) {
            String departmentDirector = getDepartmentDirector(equipmentCheckTask.getReleaseTargetId(), equipmentCheckTask.getDispatchMode());
            equipmentCheckTask.setDirector(departmentDirector);
        } else if (PERSON_GROUP_RELEASE_TARGET.equals(equipmentCheckTask.getReleaseTargetType())) {
            EquipmentPersonGroup equipmentPersonGroup = equipmentPersonGroupService.getById(EquipmentPersonGroup.class,equipmentCheckTask.getReleaseTargetId());
            if (StringUtils.isEmpty(equipmentPersonGroup.getDirectorId()) && ASSIGN_MODE.equals(equipmentCheckTask.getDispatchMode())) {
                throw new MBootException("派工模式下该下达目标无负责人");
            }
            equipmentCheckTask.setDirector(equipmentPersonGroup.getDirectorId());
        }
        save(equipmentCheckTask);
        if (equipmentCheckTaskDetailList != null && equipmentCheckTaskDetailList.size() > 0) {
            for (EquipmentCheckTaskDetail entity : equipmentCheckTaskDetailList) {
                //外键设置
                entity.setTaskId(equipmentCheckTask.getId());
                equipmentCheckTaskDetailService.save(entity);
                // 处理计划明细中的选项数据
                if (entity.getChooseEnable() == 1) {
                    List<EquipmentCommParametersDetail> equipmentCommParametersDetails = equipmentCommParametersDetailService.selectByMainId(entity.getParamId());
                    List<EquipmentCheckTaskDetailParam> checkTaskDetailParams = equipmentCommParametersDetails.stream().map(paramDetail -> {
                        EquipmentCheckTaskDetailParam taskDetailParam = new EquipmentCheckTaskDetailParam();
                        taskDetailParam.setParam(paramDetail.getParameter())
                                .setNum(paramDetail.getNum());
                        taskDetailParam.setDetailId(entity.getId())
                                .setTaskId(equipmentCheckTask.getId());
                        return taskDetailParam;
                    }).collect(Collectors.toList());
                    equipmentCheckTaskDetailParamService.save(checkTaskDetailParams);
                }
            }
        }
    }

    private String getDepartmentDirector(String departmentId, String dispatchMode) throws MBootException {
        // todo 因为底层部门维护处没有部门负责人的功能，暂时取出部门某位人员做下下达人
        List<User> users = JpaUtil.linq(User.class)
                .exists(UserDept.class)
                .equalProperty("userId", "username")
                .equal("deptId", departmentId)
                .end()
                .asc("username").list();
        if (CollectionUtils.isEmpty(users) && ASSIGN_MODE.equals(dispatchMode)) {
            throw new MBootException("派工模式下该下达目标无负责人");
        } else {
            return users.get(0).getUsername();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateMain(EquipmentCheckTask equipmentCheckTask, List<EquipmentCheckTaskDetail> equipmentCheckTaskDetailList, List<EquipmentCheckTaskTransfer> equipmentCheckTaskTransferList) throws MBootException {
        if (AREA_TARGET.equals(equipmentCheckTask.getTargetType())) {
            // 查询区域信息
            EquipmentArea area = equipmentAreaService.getById(EquipmentArea.class,equipmentCheckTask.getTargetId());
            if (area == null) {
                return;
            }
            equipmentCheckTask.setTargetCode(area.getAreaCode());
            if (area.getPid() != null && !"0".equals(area.getPid())) {
                String parentAllName = equipmentAreaService.getParentAllNameByPid(area.getPid());
                equipmentCheckTask.setTargetName(parentAllName +"/"+ area.getAreaName());
            } else {
                equipmentCheckTask.setTargetName(area.getAreaName());
            }
        }
        // 获取部门或群组的负责人
        if (DEPART_RELEASE_TARGET.equals(equipmentCheckTask.getReleaseTargetType())) {
            String departmentDirector = getDepartmentDirector(equipmentCheckTask.getReleaseTargetId(), equipmentCheckTask.getDispatchMode());
            equipmentCheckTask.setDirector(departmentDirector);
        } else if (PERSON_GROUP_RELEASE_TARGET.equals(equipmentCheckTask.getReleaseTargetType())) {
            EquipmentPersonGroup equipmentPersonGroup = equipmentPersonGroupService.getById(EquipmentPersonGroup.class,equipmentCheckTask.getReleaseTargetId());
            if (StringUtils.isEmpty(equipmentPersonGroup.getDirectorId()) && ASSIGN_MODE.equals(equipmentCheckTask.getDispatchMode())) {
                throw new MBootException("派工模式下该下达目标无负责人");
            }
            equipmentCheckTask.setDirector(equipmentPersonGroup.getDirectorId());
        }
        update(equipmentCheckTask);

//        //1.先删除子表数据
//        JpaUtil.lind(EquipmentCheckTaskDetail.class).equal("taskId", equipmentCheckTask.getId()).delete();
//        JpaUtil.lind(EquipmentCheckDetailParam.class).equal("taskId", equipmentCheckTask.getId()).delete();
//
//        //2.子表数据重新插入
//        if (equipmentCheckTaskDetailList != null && equipmentCheckTaskDetailList.size() > 0) {
//            for (EquipmentCheckTaskDetail entity : equipmentCheckTaskDetailList) {
//                //外键设置
//                entity.setTaskId(equipmentCheckTask.getId());
//                //外键设置
//                equipmentCheckTaskDetailService.save(entity);
//                // 处理计划明细中的选项数据
//                if (entity.getChooseEnable() == 1) {
//                    List<EquipmentCommParametersDetail> equipmentCommParametersDetails = equipmentCommParametersDetailService.selectByMainId(entity.getParamId());
//                    List<EquipmentCheckTaskDetailParam> checkTaskDetailParams = equipmentCommParametersDetails.stream().map(paramDetail -> {
//                        EquipmentCheckTaskDetailParam taskDetailParam = new EquipmentCheckTaskDetailParam();
//                        taskDetailParam.setParam(paramDetail.getParameter())
//                                .setNum(paramDetail.getNum());
//                        taskDetailParam.setDetailId(entity.getId())
//                                .setTaskId(equipmentCheckTask.getId());
//                        return taskDetailParam;
//                    }).collect(Collectors.toList());
//                    equipmentCheckTaskDetailParamService.save(checkTaskDetailParams);
//                }
//            }
//        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delMain(String id) {
        JpaUtil.lind(EquipmentCheckTaskDetail.class).equal("taskId", id).delete();
        JpaUtil.lind(EquipmentCheckTaskTransfer.class).equal("taskId", id).delete();
        JpaUtil.lind(EquipmentCheckTask.class).equal("id", id).delete();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delBatchMain(Collection<? extends Serializable> idList) {
        for (Serializable id : idList) {
            JpaUtil.lind(EquipmentCheckTaskDetail.class).equal("taskId", id).delete();
            JpaUtil.lind(EquipmentCheckTaskTransfer.class).equal("taskId", id).delete();
            JpaUtil.lind(EquipmentCheckTask.class).equal("id", id).delete();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void release(String id) throws MBootException {
        EquipmentCheckTask checkTask = this.getById(EquipmentCheckTask.class,id);
        if (checkTask == null) {
            return;
        }
        if (!STATUS_START.equals(checkTask.getOrderStatus())) {
            throw new MBootException("此状态下无法下达");
        }
        checkTask.setOrderStatus(STATUS_RELEASE);
        checkTask.setReleaseTime(new Date());

        if (PERSONAL_RELEASE_TARGET.equals(checkTask.getReleaseTargetType())) {
            // 如果是下达目标是个人，则直接跳过派工状态
            checkTask.setOrderStatus(STATUS_WAIT_EXECUT);
            checkTask.setDispatchTime(new Date());
            checkTask.setExecutor(checkTask.getReleaseTargetId());
        }

        update(checkTask);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void dispatch(String id, String executor) throws MBootException {
        EquipmentCheckTask checkTask = getById(EquipmentCheckTask.class,id);
        if (checkTask == null) {
            throw new MBootException("未找到对应数据");
        }
        // 判断工单状态
        if (!STATUS_RELEASE.equals(checkTask.getOrderStatus())) {
            throw new MBootException("工单状态不正确，不允许执行");
        }
//        // 判断派工模式
//        if (GRAB_MODE.equals(checkTask.getDispatchMode())) {
//            throw new MBootException("非派工模式");
//        }

        checkTask.setDispatchMode(ASSIGN_MODE);
        User loginUser = SecurityUtils.getLoginUser();
        checkTask.setExecutor(executor);
        checkTask.setDispatchTime(new Date());
        checkTask.setDispatchUser(loginUser.getUsername());
        checkTask.setOrderStatus(STATUS_WAIT_EXECUT);

        update(checkTask);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void grab(String id) throws MBootException {
        EquipmentCheckTask checkTask = getById(EquipmentCheckTask.class,id);
        if (checkTask == null) {
            throw new MBootException("工单不存在");
        }
        // 判断工单状态
        if (!STATUS_RELEASE.equals(checkTask.getOrderStatus())) {
            throw new MBootException("工单状态不正确");
        }
//        // 判断派工模式
//        if (ASSIGN_MODE.equals(checkTask.getDispatchMode())) {
//            throw new MBootException("非抢单模式");
//        }

        checkTask.setDispatchMode(GRAB_MODE);
        User loginUser = SecurityUtils.getLoginUser();
        checkTask.setExecutor(loginUser.getUsername());
        checkTask.setDispatchTime(new Date());
        checkTask.setDispatchUser(loginUser.getUsername());
        checkTask.setOrderStatus(STATUS_WAIT_EXECUT);

        update(checkTask);

    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void excut(EquipmentCheckTaskPage equipmentCheckTaskPage, HttpServletRequest request) throws MBootException {
        EquipmentCheckTask equipmentCheckTask = this.getById(EquipmentCheckTask.class,equipmentCheckTaskPage.getId());
        if (equipmentCheckTask == null) {
            throw new MBootException("未找到对应数据");
        }

        if (!STATUS_WAIT_EXECUT.equals(equipmentCheckTask.getOrderStatus())
                && !STATUS_EXECUT.equals(equipmentCheckTask.getOrderStatus())) {
            throw new MBootException("工单状态不正确，不允许执行");
        }
        if (STATUS_WAIT_EXECUT.equals(equipmentCheckTask.getOrderStatus())) {
            equipmentCheckTask.setOrderStatus(STATUS_EXECUT);
            equipmentCheckTask.setActualStartTime(new Date());
        }

        for (EquipmentCheckTaskDetail equipmentCheckTaskDetail : equipmentCheckTaskPage.getEquipmentCheckTaskDetailList()) {
            if (equipmentCheckTaskDetail.getIsRecord() == 0) {
                equipmentCheckTaskDetail.setActualVaule("无需记录");
            }
            equipmentCheckTaskDetailService.update(equipmentCheckTaskDetail);
        }

        // 查询是否有未记录的明细

        Long count = JpaUtil.linq(EquipmentCheckTaskDetail.class)
                .equal("taskId",equipmentCheckTask.getId())
                .equal("isRecord",1)
                .isNull("actualVaule")
                .count();
        if (count < 1) {
            equipmentCheckTask.setActualEndTime(new Date());
            equipmentCheckTask.setOrderStatus(STATUS_END);
        }

        this.update(equipmentCheckTask);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void startExcut(String id) throws MBootException {
        EquipmentCheckTask checkTask = getById(EquipmentCheckTask.class,id);
        if (checkTask == null) {
            return;
        }
        // 判断工单状态
        if (!STATUS_WAIT_EXECUT.equals(checkTask.getOrderStatus())) {
            throw new MBootException("工单非待开始状态");
        }
        checkTask.setActualStartTime(new Date());
        checkTask.setOrderStatus(STATUS_EXECUT);
        this.update(checkTask);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void reSend(String id, String executor, String reason) throws MBootException {

        EquipmentCheckTask checkTask = getById(EquipmentCheckTask.class,id);
        if (checkTask == null) {
            return;
        }
        // 判断工单状态
        if (checkTask.getOrderStatus() < Integer.valueOf(STATUS_WAIT_EXECUT)
                || STATUS_END.equals(checkTask.getOrderStatus())) {
            return;
        }

        EquipmentCheckTaskTransfer equipmentCheckTaskTransfer = new EquipmentCheckTaskTransfer();
        equipmentCheckTaskTransfer.setTaskId(id);
        equipmentCheckTaskTransfer.setOldExecutor(checkTask.getExecutor());
        equipmentCheckTaskTransfer.setNewExecutor(executor);
        equipmentCheckTaskTransfer.setReason(reason);
        equipmentCheckTaskTransferService.save(equipmentCheckTaskTransfer);

        checkTask.setExecutor(executor);
        this.update(checkTask);

    }


}
